<script setup lang="ts">
import { ref, computed, onMounted } from "vue"
import type { IShiki } from "./lib/inter"
import useShiki from "./lib/use"
import type { BundledLanguageInfo, BundledThemeInfo } from "@shikijs/types"
import ClipboardJS from "clipboard"

// const emits = defineEmits<{"update:modelValue":[string],"test":[void]}>()
const emits = defineEmits<IShiki.Emits>()
const props = withDefaults(defineProps<IShiki.Props>(), {
    showHeader: true,
    showCopy:true,
    showCopyOutput:true,
    decorations:() => [],
    transformers:() => [],
    lang: 'json',
    theme: "min-light"
});
const { showHeader, readonly } = props;
const outputRef = ref();
const {preStyle, input, output, bundledLanguagesInfo, bundledThemesInfo, langChange, themeChange, onInput, onScroll, onKeydown, onKeyup } = useShiki(outputRef, props)


// 添加事件 完成 v-model 指令
// addHooks((v) => emits("update:modelValue",v))
//
const langName = ref(props.lang || 'json')
const langSearch = ref('')
const langVisible = ref(false)
const langInputRef = ref()
const handleLangChange = (item: BundledLanguageInfo) => {
    langInputRef.value.value = item.name;
    langChange(item)
}
const langList = computed(() => {
    const l = bundledLanguagesInfo;
    const s = langSearch.value.toLocaleLowerCase();
    if (s) {
        return l.filter(t => t.name.toLocaleLowerCase().includes(s))
    }
    return l;
})
const handleLangBlur = () => {
    if (langInputRef.value.value == langSearch.value) {
        langInputRef.value.value = langName.value;
    }

}
const handleLangFocus = () => {
    langName.value = langInputRef.value.value;
    langSearch.value = '';
    langInputRef.value.value = ''
}
const handleLangInput = () => {
    langSearch.value = langInputRef.value.value;
}

const themeName = ref(props.theme || 'min-light')
const themeSearch = ref('')
const themeVisible = ref(false)
const themeInputRef = ref();
const handleThemeChange = (item: BundledThemeInfo) => {
    themeInputRef.value.value = item.displayName
    themeChange(item)
}
const themeList = computed(() => {
    const l = bundledThemesInfo;
    const s = themeSearch.value.toLocaleLowerCase()
    if (s) {
        return l.filter(t => t.displayName.toLocaleLowerCase().includes(s))
    }
    return l;
})
const handleThemeBlur = () => {
    if (themeInputRef.value.value == themeSearch.value) {
        themeInputRef.value.value = themeName.value;
    }
}
const handleThemeFocus = () => {
    themeName.value = themeInputRef.value.value;
    themeSearch.value = '';
    themeInputRef.value.value = ''
}
const handleThemeInput = () => {
    themeSearch.value = themeInputRef.value.value;
}

const handleInput = (e:any) => {
    emits('input',e)
    emits('update:modelValue',e.target.value)
    onInput(e)
}
const handleScroll = (e:any) => {onScroll(e)}
const handleKeydown = (e:any) => {
    emits('keydown',e)
    onKeydown(e)
}
const handleKeyup = (e:any) => {
    emits('keyup',e)
    onKeyup(e)
}
const handleBlur = (e:any) => {
    emits('blur',e)
    // onBlur(e)
}
const handleFocus = (e:any) => {
    emits('focus',e)
    // onFocus(e)
}


onMounted(() => {
    if (langInputRef.value) {
        langInputRef.value.value = props.lang.split('-').join(' ').toLocaleUpperCase();
    }
    if (themeInputRef.value) {
        themeInputRef.value.value = props.theme.split('-').join(' ').toLocaleUpperCase();
    }

    const clipboard = new ClipboardJS('.btn');

    clipboard.on('success', function (e) {
        e.clearSelection();
    });
    clipboard.on('error', function (e) {
        console.error('Action:', e.action);
        console.error('Trigger:', e.trigger);
    });
})

</script>

<template>
    <div class="pack-shiki w-full h-full relative text-14" :style="[preStyle]">
        <!-- header -->
        <div v-if="showHeader"
            class="_header relative z-999 p-y-2 p-x-10 text-10 h-28 min-h-16px box-border flex items-center gap-20">
            <div class="_lang relative w-200 b-1 b-solid b-#ddd p-y-2 p-x-4 rd-4 h-full box-border" 
                @mouseenter="langVisible = true" @mouseleave="langVisible = false">
                <input ref="langInputRef"
                    class="w-full h-full b-none shadow-none outline-none focus-op-80 bg-transparent c-inherit text-inherit"
                    placeholder="语言搜索" @focus="handleLangFocus" @blur="handleLangBlur" @input="handleLangInput" />
                <div :class="['absolute top-full left-0  shadow-[0_0_10px_0_#ddd] max-h-200 overflow-auto  rd-4 w-full box-border transition-all', langVisible ? 'op-100 h-fit p-6 mt-2' : 'op-0 h-0 p-0']"
                    :style="[preStyle]">
                    <template v-for="item in langList">
                        <div @click="handleLangChange(item)"
                            class="op-70 cursor-pointer hover-op-100 max-w-full truncate mt-2" :title="item.name">{{ item.name }}</div>
                    </template>
                </div>
            </div>

            <div class="_theme relative w-200 b-1 b-solid b-#ddd p-y-2 p-x-4 rd-4 h-full box-border" 
                @mouseenter="themeVisible = true" @mouseleave="themeVisible = false">
                <input ref="themeInputRef"
                    class="w-full h-full b-none shadow-none outline-none focus-op-80 bg-transparent c-inherit text-inherit"
                    placeholder="主题搜索" @focus="handleThemeFocus" @blur="handleThemeBlur" @input="handleThemeInput" />
                <div :class="['absolute top-full left-0 shadow-[0_0_10px_0_#ddd] max-h-200 overflow-auto rd-4 w-full box-border transition-all', themeVisible ? 'op-100 h-fit p-6 mt-2' : 'op-0 h-0 p-0']"
                    :style="[preStyle]">
                    <template v-for="item in themeList">
                        <div @click="handleThemeChange(item)"
                            class="op-70 cursor-pointer hover-op-100 max-w-full truncate mt-2" :title="item.displayName">{{ item.displayName }}
                        </div>
                    </template>
                </div>
            </div>

            <div v-if="props.showCopyOutput && output && input" class="i-uiw:copy btn text-16 cursor-pointer op-70 hover-op-100" :data-clipboard-text="output" title="复制格式化文本"></div>
        </div>
        <div :class="['_body relative  p-10 w-full box-border ', showHeader ? 'h-[calc(100%-7rem)]' : 'h-full']">
            <div class="absolute top-0 left-0 w-full h-full p-10 box-border overflow-hidden">
                <div ref="outputRef" class="w-full h-full overflow-auto" v-html="output"></div>
            </div>
            <textarea v-if="!readonly" :value="input"
                class="relative block w-full h-full z-99 bg-transparent text-transparent b-none outline-none shadow-none caret-gray overflow-auto resize-none text-size-inherit"
                autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" 
                @input="handleInput"
                @blur="handleBlur"
                @focus="handleFocus"
                @scroll="handleScroll" 
                @keyDown="handleKeydown" 
                @keyUp="handleKeyup" ></textarea>
            <div v-if="showCopy && input" class="i-qlementine-icons:copy-16 btn absolute z-999 text-16 right-1em top-1em cursor-pointer op-30 hover-op-100"
                :data-clipboard-text="input" title="复制原文本">
            </div>
        </div>
    </div>
</template>

<style>
* {
    padding: 0;
    margin: 0
}

html {
    font-size:4px;
    /* font-size: calc(100vw / 1920 * 4); */
}

@media screen and(min-width:1900px){
    html{
        font-size: calc(100vw / 1920 * 4);
    }
}

/* 滚动条优化 */
/* 为滚动条整体设置样式 */
::-webkit-scrollbar {
    width: 6px;
    height: 6px;
}

/* 为滚动条的轨道设置样式 */
::-webkit-scrollbar-track {
    background: rgba(#101F1C, 0.1);
    border-radius: 6px;
}

/* 为滚动条的滑块设置样式 */
::-webkit-scrollbar-thumb {
    background-color: rgba(144, 147, 153, .1);
    border-radius: 6px;
    transition: background-color .3s;
    cursor: pointer;
}

/* 当鼠标悬停在滑块上时改变滑块的颜色 */
::-webkit-scrollbar-thumb:hover {
    background-color: rgba(144, 147, 153, .3);
}
</style>